<?php
namespace Swiftx\Component\Router;
use Swiftx\Interfaces\Ioc\Container;
use Swiftx\Interfaces\Router\Dispatcher as DispatcherInterface;
use Swiftx\Interfaces\Router\Request as RequestInterface;

/**
 * 路由分发器
 *
 * @author		胡永强  <odaytudio@gmail.com>
 * @since		2015-10-09
 * @copyright	Copyright (c) 2014-2015 Swiftx Inc.
 */
abstract class Dispatcher implements DispatcherInterface{

    /**
     * 目标主机
     * @var string
     */
    protected $host = null;

    /**
     * 请求目标文档
     * @var string
     */
    protected $document = null;

    /**
     * 文档适配规则
     * @var string
     */
    protected $document_rule;

    /**
     * 允许访问的方法
     * @var string[]
     */
    protected $method = [];

    /**
     * 依赖注入容器
     * @var Container
     */
    protected $container;

    /**
     * 设置主机名
     * @param string $value
     * @return DispatcherInterface
     */
    public function setHost(string $value):DispatcherInterface{
        $this->host = $value;
        return $this;
    }

    /**
     * 设置目标文档
     * @param string $value
     * @return DispatcherInterface
     */
    public function setDocument(string $value):DispatcherInterface{
        $this->document = $value;
        $value = preg_replace('/\{([^\{\}]+)\}/','(?P<${1}>.+)', $value);
        $this->document_rule = '/^'.addcslashes($value,'/').'$/';
        return $this;
    }

    /**
     * 允许访问的方法
     * @param string $value
     * @return DispatcherInterface
     */
    public function setMethod(string $value):DispatcherInterface{
        $this->method[] = strtoupper($value);
        return $this;
    }

    /**
     * 允许访问的方法
     * @return string
     */
    public function getMethod():string {
        return $this->method[0];
    }

    /**
     * 依赖注入容器
     * @param Container $container
     * @auto-injection
     */
    public function setContainer(Container $container){
        $this->container = $container;
    }

    /**
     * 验证主机名
     * @param string $value
     * @return bool
     */
    protected function checkHost(string $value):bool {
        if($this->host == null) return true;
        return $this->host != $value;
    }

    /**
     * 设置请求方式
     * @param string $value
     * @return bool
     */
    protected function checkMethod(string $value):bool {
        if(empty($this->method)) return true;
        return in_array($value, $this->method);
    }

    /**
     * 验证目标文档
     * @param string $value
     * @param array $params
     * @return bool
     */
    protected function checkDocument(string $value, array &$params = null):bool {
        if($this->document == null) return true;
        if($params === null)
            return (bool)preg_match($this->document_rule, $value);
        return (bool)preg_match($this->document_rule, $value, $params, 0);
    }

    /**
     * 解析请求参数
     * @param RequestInterface $request
     */
    protected function parseParams(RequestInterface $request){
        $params = [];
        $this->checkDocument($request->getDocument(), $params);
        $request->setParams($params);
    }

    /**
     * 匹配参数
     * @param RequestInterface $request
     * @return bool
     */
    public function pattern(RequestInterface $request):bool {
        if(!$this->checkHost($request->getHost())) return false;
        if(!$this->checkMethod($request->getMethod())) return false;
        return $this->checkDocument($request->getDocument());
    }

    /**
     * 生成请求地址
     * @param string[] ...$args
     * @return string
     */
    public function uri(string ...$args):string{
        return $this->document;
    }

}